{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Notebook to measure the performance of DeepMEL\n",
    "#### Following codes in this notebook were run using conda environments\n",
    "#### Here are the used packages and their version"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "#cpu\n",
    "conda create --name DeepMEL_conda_env_cpu python=3.6 tensorflow=1.14.0 keras=2.2.4\n",
    "conda activate DeepMEL_conda_env_cpu\n",
    "conda install numpy=1.16.2 matplotlib=3.1.1 shap=0.29.3 ipykernel=5.1.2\n",
    "\n",
    "#gpu\n",
    "conda create --name DeepMEL_conda_env_gpu python=3.6 tensorflow-gpu=1.14.0 keras-gpu=2.2.4\n",
    "conda activate DeepMEL_conda_env_gpu\n",
    "conda install numpy=1.16.2  matplotlib=3.1.1 shap=0.29.3 ipykernel=5.1.2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Loading necessary packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import sys\n",
    "import optparse\n",
    "from array import *\n",
    "\n",
    "import tensorflow\n",
    "import numpy as np\n",
    "\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "import sklearn\n",
    "from sklearn.utils import class_weight, shuffle\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.metrics import average_precision_score, roc_auc_score\n",
    "\n",
    "from keras.models import Sequential\n",
    "from keras.models import model_from_json\n",
    "from keras.layers.core import Dense, Dropout, Activation, Flatten\n",
    "from keras.layers.convolutional import Conv1D, MaxPooling1D\n",
    "from keras.layers import Bidirectional, Concatenate, PReLU \n",
    "from keras.optimizers import RMSprop, Adam\n",
    "from keras.callbacks import ModelCheckpoint, EarlyStopping\n",
    "from keras import regularizers\n",
    "from keras.layers.wrappers import Bidirectional, TimeDistributed\n",
    "from keras.layers.recurrent import LSTM\n",
    "from keras.layers import Layer, average, Input\n",
    "from keras.models import Model\n",
    "from keras.utils import plot_model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Defining necessary functitons"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_output(input_layer, hidden_layers):\n",
    "    output = input_layer\n",
    "    for hidden_layer in hidden_layers: \n",
    "        output = hidden_layer(output)\n",
    "    return output\n",
    "\n",
    "def build_model():\n",
    "    forward_input = Input(shape=seq_shape)\n",
    "    reverse_input = Input(shape=seq_shape)\n",
    "\n",
    "    hidden_layers = [\n",
    "        Conv1D(128, kernel_size=20, padding=\"valid\", activation='relu', kernel_initializer='random_uniform'),\n",
    "        MaxPooling1D(pool_size=10, strides=10, padding='valid'),\n",
    "        Dropout(0.2),\n",
    "        TimeDistributed(Dense(128, activation='relu')),\n",
    "        Bidirectional(LSTM(128, dropout=0.1, recurrent_dropout=0.1, return_sequences=True)),\n",
    "        Dropout(0.2),\n",
    "        Flatten(),\n",
    "        Dense(256, activation='relu'),\n",
    "        Dropout(0.4),\n",
    "        Dense(len(selected_classes), activation='sigmoid')]\n",
    "    forward_output = get_output(forward_input, hidden_layers)     \n",
    "    reverse_output = get_output(reverse_input, hidden_layers)\n",
    "    output = average([forward_output, reverse_output])\n",
    "    model = Model(input=[forward_input, reverse_input], output=output)\n",
    "\n",
    "    model.summary()\n",
    "    model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])\n",
    "    return model\n",
    "\n",
    "def readfile(filename):\n",
    "    ids = []\n",
    "    ids_d = {}\n",
    "    seqs = {}\n",
    "    classes = {}\n",
    "    f = open(filename, 'r')\n",
    "    lines = f.readlines()\n",
    "    f.close()\n",
    "    seq = []\n",
    "    for line in lines:\n",
    "        if line[0] == '>':\n",
    "            ids.append(line[1:].rstrip('\\n'))\n",
    "            if line[1:].rstrip('\\n').split('_')[0] not in seqs:\n",
    "                seqs[line[1:].rstrip('\\n').split('_')[0]] = []\n",
    "            if line[1:].rstrip('\\n').split('_')[0] not in ids_d:\n",
    "                ids_d[line[1:].rstrip('\\n').split('_')[0]] = line[1:].rstrip('\\n').split('_')[0]\n",
    "            if line[1:].rstrip('\\n').split('_')[0] not in classes:\n",
    "                classes[line[1:].rstrip('\\n').split('_')[0]] = np.zeros(NUM_CLASSES)\n",
    "            classes[line[1:].rstrip('\\n').split('_')[0]][int(line[1:].rstrip('\\n').split('_')[1])-1] = 1        \n",
    "            if seq != []: seqs[ids[-2].split('_')[0]]= (\"\".join(seq))\n",
    "            seq = []\n",
    "        else:\n",
    "            seq.append(line.rstrip('\\n').upper())\n",
    "    if seq != []:\n",
    "        seqs[ids[-1].split('_')[0]]=(\"\".join(seq))\n",
    "    return ids,ids_d,seqs,classes\n",
    "\n",
    "def one_hot_encode_along_row_axis(sequence):\n",
    "    to_return = np.zeros((1,len(sequence),4), dtype=np.int8)\n",
    "    seq_to_one_hot_fill_in_array(zeros_array=to_return[0],\n",
    "                                 sequence=sequence, one_hot_axis=1)\n",
    "    return to_return\n",
    "\n",
    "def seq_to_one_hot_fill_in_array(zeros_array, sequence, one_hot_axis):\n",
    "    assert one_hot_axis==0 or one_hot_axis==1\n",
    "    if (one_hot_axis==0):\n",
    "        assert zeros_array.shape[1] == len(sequence)\n",
    "    elif (one_hot_axis==1): \n",
    "        assert zeros_array.shape[0] == len(sequence)\n",
    "    for (i,char) in enumerate(sequence):\n",
    "        if (char==\"A\" or char==\"a\"):\n",
    "            char_idx = 0\n",
    "        elif (char==\"C\" or char==\"c\"):\n",
    "            char_idx = 1\n",
    "        elif (char==\"G\" or char==\"g\"):\n",
    "            char_idx = 2\n",
    "        elif (char==\"T\" or char==\"t\"):\n",
    "            char_idx = 3\n",
    "        elif (char==\"N\" or char==\"n\"):\n",
    "            continue\n",
    "        else:\n",
    "            raise RuntimeError(\"Unsupported character: \"+str(char))\n",
    "        if (one_hot_axis==0):\n",
    "            zeros_array[char_idx,i] = 1\n",
    "        elif (one_hot_axis==1):\n",
    "            zeros_array[i,char_idx] = 1\n",
    "\n",
    "def create_plots(history):\n",
    "    plt.plot(history.history['acc'])\n",
    "    plt.plot(history.history['val_acc'])\n",
    "    plt.title('model accuracy')\n",
    "    plt.ylabel('accuracy')\n",
    "    plt.xlabel('epoch')\n",
    "    plt.legend(['train', 'test'], loc='upper left')\n",
    "    plt.savefig(foldername + 'accuracy.png')\n",
    "    plt.clf()\n",
    "\n",
    "    plt.plot(history.history['loss'])\n",
    "    plt.plot(history.history['val_loss'])\n",
    "    plt.title('model loss')\n",
    "    plt.ylabel('loss')\n",
    "    plt.xlabel('epoch')\n",
    "    plt.legend(['train', 'test'], loc='upper left')\n",
    "    plt.savefig(foldername + 'loss.png')\n",
    "    plt.clf()\n",
    "    \n",
    "def json_hdf5_to_model(json_filename, hdf5_filename):  \n",
    "    with open(json_filename, 'r') as f:\n",
    "        model = model_from_json(f.read())\n",
    "    model.load_weights(hdf5_filename)\n",
    "    return model\n",
    "\n",
    "def loc_to_model_loss(loc):\n",
    "    return json_hdf5_to_model(loc + 'model.json', loc + 'model_best_loss.hdf5')\n",
    "\n",
    "def shuffle_label(label):\n",
    "    for i in range(len(label.T)):\n",
    "        label.T[i] = shuffle(label.T[i])\n",
    "    return label\n",
    "\n",
    "def calculate_roc_pr(score, label):\n",
    "    output = np.zeros((len(label.T), 2))\n",
    "    for i in range(len(label.T)):\n",
    "        roc_ = roc_auc_score(label.T[i], score.T[i])\n",
    "        pr_ = average_precision_score(label.T[i], score.T[i])\n",
    "        output[i] = [roc_, pr_]\n",
    "    return output"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Preparing the input data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Prepare input...\n"
     ]
    }
   ],
   "source": [
    "NUM_CLASSES = 24\n",
    "selected_classes = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24])-1\n",
    "SEQ_LEN = 500\n",
    "SEQ_DIM = 4\n",
    "seq_shape = (SEQ_LEN, SEQ_DIM)\n",
    "\n",
    "foldername = '/results/'\n",
    "train_filename = '/summits_to_topics_wochr2.fa'\n",
    "test_filename = '/summits_to_topics_chr2.fa'\n",
    "\n",
    "print(\"Prepare input...\")\n",
    "train_ids, train_ids_d, train_seqs, train_classes = readfile(train_filename)\n",
    "X_train = np.array([one_hot_encode_along_row_axis(train_seqs[id]) for id in train_ids_d]).squeeze(axis=1)\n",
    "y_train = np.array([train_classes[id] for id in train_ids_d])\n",
    "y_train = y_train[:,selected_classes]\n",
    "X_train = X_train[y_train.sum(axis=1)>0]\n",
    "y_train = y_train[y_train.sum(axis=1)>0]\n",
    "X_train_rc = X_train[:,::-1,::-1]\n",
    "train_data = [X_train, X_train_rc]\n",
    "\n",
    "test_ids, test_ids_d, test_seqs, test_classes = readfile(test_filename)\n",
    "X_test = np.array([one_hot_encode_along_row_axis(test_seqs[id]) for id in test_ids_d]).squeeze(axis=1)\n",
    "y_test = np.array([test_classes[id] for id in test_ids_d])\n",
    "y_test = y_test[:,selected_classes]\n",
    "X_test = X_test[y_test.sum(axis=1)>0]\n",
    "y_test = y_test[y_test.sum(axis=1)>0]\n",
    "X_test_rc = X_test[:,::-1,::-1]\n",
    "test_data = [X_test, X_test_rc]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Loading the trained DeepMEL model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: Logging before flag parsing goes to stderr.\n",
      "W0421 18:19:06.987329 47906138156672 deprecation_wrapper.py:119] From /staging/leuven/stg_00002/lcb/itask/programs/anaconda3/envs/deeplearning/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:517: The name tf.placeholder is deprecated. Please use tf.compat.v1.placeholder instead.\n",
      "\n",
      "W0421 18:19:07.009386 47906138156672 deprecation_wrapper.py:119] From /staging/leuven/stg_00002/lcb/itask/programs/anaconda3/envs/deeplearning/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:74: The name tf.get_default_graph is deprecated. Please use tf.compat.v1.get_default_graph instead.\n",
      "\n",
      "W0421 18:19:07.011919 47906138156672 deprecation_wrapper.py:119] From /staging/leuven/stg_00002/lcb/itask/programs/anaconda3/envs/deeplearning/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:4138: The name tf.random_uniform is deprecated. Please use tf.random.uniform instead.\n",
      "\n",
      "W0421 18:19:07.038405 47906138156672 deprecation_wrapper.py:119] From /staging/leuven/stg_00002/lcb/itask/programs/anaconda3/envs/deeplearning/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:3976: The name tf.nn.max_pool is deprecated. Please use tf.nn.max_pool2d instead.\n",
      "\n",
      "W0421 18:19:07.044372 47906138156672 deprecation_wrapper.py:119] From /staging/leuven/stg_00002/lcb/itask/programs/anaconda3/envs/deeplearning/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:133: The name tf.placeholder_with_default is deprecated. Please use tf.compat.v1.placeholder_with_default instead.\n",
      "\n",
      "W0421 18:19:07.052615 47906138156672 deprecation.py:506] From /staging/leuven/stg_00002/lcb/itask/programs/anaconda3/envs/deeplearning/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:3445: calling dropout (from tensorflow.python.ops.nn_ops) with keep_prob is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use `rate` instead of `keep_prob`. Rate should be set to `rate = 1 - keep_prob`.\n",
      "W0421 18:19:08.984502 47906138156672 deprecation_wrapper.py:119] From /staging/leuven/stg_00002/lcb/itask/programs/anaconda3/envs/deeplearning/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py:174: The name tf.get_default_session is deprecated. Please use tf.compat.v1.get_default_session instead.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "trained_model = loc_to_model_loss('/path_to_model/')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Calculating auROC and auPR values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "calculate roc and pr...\n"
     ]
    },
    {
     "data": {
      "image/png": "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zPzhH/7hvK+/cuXKbNiwoetmAAAAAACMRJfB9MeTPKGqzq+qk5NckeR9By5QVecleW+Sf9Za+9sOa1kQvv/7vz933nnnw9Of+9zncv/99+c3f/M3c9111837e5dddlluvfXW3H777aMoEwAAAACgU50F0621B5NcneQDSW5L8gettVur6qqqump2sX+T5Mwk/7GqtlbVlq7qOcjMTLJ6dbJkyeBxZqbzP/nQQw9l8+bNeeELX/jwvOuuuy5XXnllfvAHfzC33357vvKVr8z5u0uWLMkv//Iv59/+23/beZ0AAAAAAF3rssd0Wms3ttae2Fp7fGttw+y8t7XW3jb780+31r6jtbZm9t9Ul/UkGYTQ69YlO3YkrQ0e163rLJz++7//+6xZsyZnnnlmvvrVr+Z5z3vew89df/31ueKKK7JkyZL8xE/8RN797nfP+zo/+ZM/mZtuuilf+MIXOqkTAAAAAGBUOg2mF6T165M9ew6et2fPYH4HTjvttGzdujU7duzIAw888PAY05/61Kfy2c9+Ns973vOyevXqXH/99YcdzmPZsmX5hV/4hbz+9a/vpE4AAAAAgFFZfMH0zp3HNn9IVqxYkbe85S154xvfmL179+a6667La1/72mzfvj3bt2/PXXfdlTvvvDM7duyY9zVe/vKX50Mf+lDuueeeTmsFAAAAAOjS4gumzzvv2OYP0fd93/floosuyvXXX5/rr78+L3rRiw56/kUvelGuv/76eX//5JNPzqte9ap5x6IGAAAAAJgE1Vobdw3HZGpqqm3ZcvA9Em+77bY85SlPOboX2D/G9IHDeSxfnmzcmExPD7HS/jim/18AAAAAgCRVdfN89xVcfD2mp6cHIfSqVUnV4FEoDQAAAAAwMsvGXcBYTE8LogEAAAAAxmTx9ZgGAAAAAGCsBNMAAAAAAIyUYBoAAAAAgJESTAMAAAAAMFKL8+aHQ3bfffdl7dq1SZIvfelLWbp0ac4+++wkySc/+clcdNFFDy97xRVX5DWveU3e//7351//63+dffv2Ze/evXn1q1+de++9N+9+97uTJNu2bcuFF16YJPmpn/qpvOpVrxpxqwAAAAAAulGttXHXcEympqbali1bDpp322235SlPecqYKjrYa1/72pxxxhn5xV/8xSTJGWeckfvvv/+gZfbu3ZtVq1blr//6r7Ny5cp861vf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\n",
      "text/plain": [
       "<Figure size 1800x720 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "print('calculate roc and pr...')\n",
    "roc_pr_dict = {\"train\": {}, \"test\": {}, \"shuffle\": {}}\n",
    "roc_pr_dict[\"train\"][\"score\"] = trained_model.predict(train_data)\n",
    "roc_pr_dict[\"train\"][\"label\"] = y_train\n",
    "roc_pr_dict[\"test\"][\"score\"] = trained_model.predict(test_data)\n",
    "roc_pr_dict[\"test\"][\"label\"] = y_test\n",
    "roc_pr_dict[\"shuffle\"][\"score\"] = np.array(roc_pr_dict[\"train\"][\"score\"], copy=True)\n",
    "roc_pr_dict[\"shuffle\"][\"label\"] = shuffle_label(np.array(y_train, copy=True))\n",
    "\n",
    "for sets in [\"train\", \"test\", \"shuffle\"]:\n",
    "    roc_pr_dict[sets][\"roc_pr\"] = calculate_roc_pr(roc_pr_dict[sets][\"score\"], roc_pr_dict[sets][\"label\"])\n",
    "\n",
    "fig = plt.figure(figsize=(25, 10))\n",
    "ax = fig.add_subplot(2, 1, 1)\n",
    "ax.set_ylabel('auROC')\n",
    "ax.scatter(list(range(24)), roc_pr_dict[\"train\"][\"roc_pr\"].T[0], color='red', label='TRAIN')\n",
    "ax.scatter(list(range(24)), roc_pr_dict[\"test\"][\"roc_pr\"].T[0], color='blue', label='TEST')\n",
    "ax.scatter(list(range(24)), roc_pr_dict[\"shuffle\"][\"roc_pr\"].T[0], color='gray', label='SHUFFLED')\n",
    "ax.set_ylim([0, 1])\n",
    "_ = plt.xticks(range(len(selected_classes)),range(1,len(selected_classes)+1))\n",
    "ax.legend()\n",
    "\n",
    "ax = fig.add_subplot(2, 1, 2)\n",
    "ax.set_ylabel('auPR')\n",
    "ax.scatter(list(range(24)), roc_pr_dict[\"train\"][\"roc_pr\"].T[1], color='red', label='TRAIN')\n",
    "ax.scatter(list(range(24)), roc_pr_dict[\"test\"][\"roc_pr\"].T[1], color='blue', label='TEST')\n",
    "ax.scatter(list(range(24)), roc_pr_dict[\"shuffle\"][\"roc_pr\"].T[1], color='gray', label='SHUFFLED')\n",
    "ax.set_ylim([0, 1])\n",
    "_ = plt.xticks(range(len(selected_classes)),range(1,len(selected_classes)+1))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "SSH r06i00n13 Deeplearning conda",
   "language": "python3",
   "name": "rik_ssh_r06i00n13_deeplearningconda"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
